﻿using System;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using Object = UnityEngine.Object;

namespace Framework
{
    public class Resource : ReferenceCountable, IDisposable
    {
        public event Action<Resource> Completed;
        
        public string url { get; private set; }
        public AssetType assetType { get; private set; }
        public ResStorageType storageType { get; private set; }
        public int loadType { get; private set; }
        public bool isDone { get; private set; }
        public string error { get; private set; }

        private Object _asset;
        private AsyncOperationHandle<Object> _handle;
        private byte[] _bytes;
        private string _text;

        public Resource(string url, int loadType)
        {
            this.url = url;
            this.loadType = loadType;
            this.assetType = AssetTypeUtil.GetAssetType(url);
            this.storageType = ResStorageTypeUtil.GetResStorageType(url);
            this.isDone = false;
        }

        public void Dispose()
        {
            Completed = null;
            isDone = false;
            _asset = null;
            _bytes = null;
            _text = null;
            Addressables.Release(_handle);
        }
        
        public void SetAsset(Object asset)
        {
            _asset = asset;
            OnCompleted();
        }

        public void SetError(string error)
        {
            this.error = error;
            OnCompleted();
        }

        public void SetHandle(AsyncOperationHandle<Object> handle)
        {
            _handle = handle;
            _asset = handle.Result;
            OnCompleted();
        }
        
        public void SetBytes(byte[] bytes)
        {
            _bytes = bytes;
            OnCompleted();
        }

        public void SetText(string text)
        {
            _text = text;
            OnCompleted();
        }

        public Object GetAsset()
        {
            return _asset;
        }

        public T GetAsset<T>() where T : Object
        {
            return (T) _asset;
        }

        public byte[] GetBytes()
        {
            return _bytes;
        }

        public string GetText()
        {
            return _text;
        }
        
        public void Reset()
        {
            isDone = false;
            error = null;
        }

        public bool HasCompletedEvent()
        {
            return Completed != null;
        }

        private void OnCompleted()
        {
            isDone = true; 
            if (Completed != null)
            {
                Completed.Invoke(this);
            }
        }
    }
}